package per.hnvcam.hedge.algebra.impl;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import per.hnvcam.common.OrderedSet;
import per.hnvcam.common.impl.OrderedSetImpl;
import per.hnvcam.hedge.algebra.FuzzyQuantifier;
import per.hnvcam.hedge.algebra.HedgeAlgebraDefinition;

@Service("FuzzyQuantifier")
public class FuzzyQuantifierImpl implements FuzzyQuantifier, InitializingBean {

   private HedgeAlgebraDefinition hedgeAlgebraDefinition;

   @Autowired
   public FuzzyQuantifierImpl(@Qualifier("HedgeAlgebraDefinition") HedgeAlgebraDefinition hedgeAlgebraDefinition) {
      this.hedgeAlgebraDefinition = hedgeAlgebraDefinition;
   }

   @Override
   public double getQuantify(String compound) {
      int pos = compound.lastIndexOf(" ");
      if (pos > 0) {
         String term = compound.substring(pos + 1, compound.length()).trim();
         return getQuantifyOfTerm(term) + hedgeAlgebraDefinition.getSign(compound) * (
            hedgeAlgebraDefinition.getFunctionMeterValue(compound) * (1 - getOmega(compound))
         );
      } else {
         return getQuantifyOfTerm(compound);
      }
   }

   private double getQuantifyOfTerm(String term) {
      if (hedgeAlgebraDefinition.getPositiveG().getAt(0).equals(term)) {
         return getNeutralValue() + hedgeAlgebraDefinition.getAlpha() * hedgeAlgebraDefinition.getFunctionMeterValue(hedgeAlgebraDefinition.getPositiveG().getAt(0));
      } else if (hedgeAlgebraDefinition.getNegativeG().getAt(0).equals(term)) {
         return hedgeAlgebraDefinition.getBeta() * getNeutralValue();
      } else {
         throw new IllegalArgumentException("Could not determine Fuzzy Quantity of term \"" + term + "\"");
      }
   }

   @Override
   public void refresh() {
      hedgeAlgebraDefinition.refresh();
   }

   @Override
   public OrderedSet<Double> getFuzzyQuantifyRanges() {
      OrderedSet<Double> result = new OrderedSetImpl<Double>();
      for (String x : hedgeAlgebraDefinition.getDomain()) {
         System.out.println(x + " = " + getQuantify(x));
         result.add(getQuantify(x));
      }
      result.add(1.0);
      return result;
   }

   private double getOmega(String compound) {
      return 0.5 * (1 + hedgeAlgebraDefinition.getSign(compound) *
         hedgeAlgebraDefinition.getSign(hedgeAlgebraDefinition.getPositiveH().last() + " " + compound) *
         (hedgeAlgebraDefinition.getBeta() - hedgeAlgebraDefinition.getAlpha()));
   }

   private double getNeutralValue() {
      return hedgeAlgebraDefinition.getFunctionMeterValue(hedgeAlgebraDefinition.getNegativeG().getAt(0));
   }

   @Override
   public void afterPropertiesSet() throws Exception {
      refresh();
   }
}
